package org.dna.metronomo.persistence.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.dna.metronomo.persistence.IActivityDAO;
import org.dna.metronomo.persistence.PersistenceException;
import org.dna.mybatis.criteria.Criteria;
import org.tigris.scarab.mapper.ActivityMapper;
import org.tigris.scarab.model.Activity;

public class IBatisActivityDAO extends IBatisMetronomoDAO
        implements IActivityDAO {

    private static final Logger LOG = Logger.getLogger(IBatisActivityDAO.class);

    public List<Activity> allActivities() throws PersistenceException {
        return executeInSession(new SessionExecutor<List<Activity>>() {

            @SuppressWarnings("unchecked")
            public List<org.tigris.scarab.model.Activity> execute(SqlSession session) throws SQLException {
                ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                return mapper.listAll();
            }
        });
    }

    public void addNewActivity(final Activity activity)
            throws PersistenceException {
        executeInSession(new SessionExecutor<Void>() {

            public Void execute(SqlSession session) throws SQLException {
                ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                mapper.insert(activity);

                LOG.info("Executing ActivityMapper.insert, inserted with " + activity);
                return null;
            }
        });
    }

    public void deleteActivityByExample(final Criteria criteria) {
        executeInSession(new SessionExecutor<Void>() {

            public Void execute(SqlSession session) throws SQLException {
                if (!criteria.verify()) {
                    return null;
                }
                criteria.bind(session.getConfiguration());
                ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                mapper.deleteByExample(criteria);
                return null;
            }
        });
    }

    public void deleteActivityByID(final long id) {
        executeInSession(new SessionExecutor<Void>() {

            public Void execute(SqlSession session) throws SQLException {
                Activity activity = new QueryByIDExecutor(id).execute(session);
                if (activity == null) {
                    return null;
                }

                ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                mapper.deleteByID(activity.getActivityId());
                return null;
            }
        });
    }

    public void updateByID(final Activity activity) throws PersistenceException {
        executeInSession(new SessionExecutor<Void>() {

            public Void execute(SqlSession session) throws SQLException {
                ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                mapper.updateByID(activity);
                return null;
            }
        });
    }

    public List<Activity> queryActivityByExample(final Criteria criteria)
            throws PersistenceException {
        return executeInSession(new SessionExecutor<List<Activity>>() {

            @SuppressWarnings("unchecked")
            public List<Activity> execute(SqlSession session) throws SQLException {
                if (!criteria.verify()) {
                    return null;
                }
                criteria.bind(session.getConfiguration());
                ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                return mapper.selectByExample(criteria);
            }
        });
    }

    public Activity queryActivityByID(final long id) {
        return executeInSession(new QueryByIDExecutor(id));
    }

    public int countByExample(final Criteria criteria) throws PersistenceException {
        return executeInSession(new SessionExecutor<Integer>() {

            @SuppressWarnings("unchecked")
            public Integer execute(SqlSession session) throws SQLException {
                ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                return mapper.countByExample(criteria);
            }
        });
    }

    private static class QueryByIDExecutor implements SessionExecutor<Activity> {

        long id;

        public QueryByIDExecutor(long id) {
            this.id = id;
        }

        @SuppressWarnings("unchecked")
        public Activity execute(SqlSession session) throws SQLException {
            ActivityMapper mapper = session.getMapper(ActivityMapper.class);
            return mapper.selectByID(id);
        }
    }
}
